﻿// <copyright file="Geometry.cs" company="Signal Processing Lab, Wuhan University">
// Copyright (c) 2009-2010 All Right Reserved
// </copyright>
// <author>Xinping Deng</author>
// <email>dentoby@gmail.com</email>
// <date>2010-4</date>
// <summary>This is part of Image.NET project.</summary>

namespace SPLWHU.Core.Vectors
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// The well-known binary geometry types (Open GIS stardard, http://www.opengeospatial.org/). 
    /// </summary>
    public enum GeometryType
    {
        /// <summary>
        /// Unkown type (default type).
        /// </summary>
        Unknown = 0,

        /// <summary>
        /// Point type.
        /// </summary>
        Point = 1,

        /// <summary>
        /// Linestring type.
        /// </summary>
        LineString = 2,

        /// <summary>
        /// Polygon type.
        /// </summary>
        Polygon = 3,

        /// <summary>
        /// Multi point type.
        /// </summary>
        MultiPoint = 4,

        /// <summary>
        /// Multi line string type.
        /// </summary>
        MultiLineString = 5,

        /// <summary>
        /// Multi polygon type.
        /// </summary>
        MultiPolygon = 6,

        /// <summary>
        /// Geometry collection.
        /// </summary>
        GeometryCollection = 7,
    }

    /// <summary>
    /// The geometry class provides access to the point count, geometry count, and so on.
    /// </summary>
    public class Geometry
    {
        /// <summary>
        /// Determines whether the geometry is valid or not.
        /// </summary>
        protected bool isValid = false;

        /// <summary>
        /// Gets the centroid of this instance. Normally, returns the centroid of the bounding box.
        /// </summary>
        /// <value>The centroid of this instance.</value>
        public virtual Point2d Centroid
        {
            // This property must be override in the derived class.
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is valid.
        /// </summary>
        /// <value><c>true</c> if this instance is valid; otherwise, <c>false</c>.</value>
        public bool IsValid
        {
            get { return this.isValid; }
        }

        /// <summary>
        /// Gets the corresponding wkb geometry type (<see cref="GeometryType"/>).
        /// </summary>
        /// <value>An int represents the wkb geometry type.</value>
        public virtual int TypeFlag
        {
            get { return (int)GeometryType.Unknown; }
        }

        /// <summary>
        /// Gets the point count in this geometry. 
        /// </summary>
        /// <remarks>
        /// A geometry instance except <see cref="Point2d"/> or <see cref="LineString"/> returns zero.
        /// </remarks>
        /// <value>The point count.</value>
        public virtual int PointCount
        {
            get { return 0; }
        }

        /// <summary>
        /// Gets the geometry count in this geometry.
        /// </summary>
        /// <remarks>
        /// A <see cref="Point2d"/> or <see cref="LineString"/> instance return zero.
        /// </remarks>
        /// <value>The geometry count.</value>
        public virtual int GeometryCount
        {
            get { return 0; }
        }

        /// <summary>
        /// Gets the point in this geometry at the specified index.
        /// </summary>
        /// <param name="index">The point index.</param>
        /// <returns>The point at the specified position.</returns>
        public virtual Point2d GetPoint(int index)
        {
            throw new VectorException("Access the point in {0} at {1} failed.", (GeometryType)this.TypeFlag, index);
        }

        /// <summary>
        /// Appends a point to this geometry.
        /// </summary>
        /// <param name="point">The point to add.</param>
        public virtual void AddPoint(Point2d point)
        {
            throw new VectorException("Add a point to {0} failed.", (GeometryType)this.TypeFlag);
        }

        /// <summary>
        /// Creates a new geometry and adds it to this instance.
        /// </summary>
        /// <returns>The geometry created.</returns>
        public virtual Geometry CreateGeometry()
        {
            throw new VectorException("Create geometry in {0} failed.", (GeometryType)this.TypeFlag);
        }

        /// <summary>
        /// Gets the geometry in this instance at the specified index.
        /// </summary>
        /// <param name="index">The geometry index.</param>
        /// <returns>The geometry at the specified position.</returns>
        public virtual Geometry GetGeometry(int index)
        {
            throw new VectorException("Access the geometry in {0} at {1} failed.", (GeometryType)this.TypeFlag, index);
        }

        /// <summary>
        /// Gets the bounding box of this geometry.
        /// </summary>
        /// <returns>The bounding box of this geometry.</returns>
        public virtual BoundingBox GetExtents()
        {
            // This method must be override in the derived class.
            return null;
        }

        /// <summary>
        /// Creates a copy of this geometry.
        /// </summary>
        /// <returns>The copy of this geometry.</returns>
        public virtual Geometry Clone()
        {
            // This method must be override in the derived class.
            return null;
        }
    }
}
